package com.lin.filegraph.utils.cluster;

import com.lin.filegraph.utils.compdg.ComponentEdge;
import com.lin.filegraph.utils.compdg.ComponentGraph;
import com.lin.filegraph.utils.compdg.ComponentNode;
import com.lin.filegraph.utils.name.DirSimilarity;
import com.lin.filegraph.utils.threshold.Threshold;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 16:08
 */

public class ClusterDistance {

    /**
     * 判断是否是小规模
     */
    public static boolean isOverSize(ComponentNode cn, ComponentGraph graph) {
        if (cn.getAllFiles().size() > Threshold.COMSCALE * graph.getTotalSize())
            return true;
        return false;
    }

    public static void getModule(){

    }

    /**
     * 判断是否是小规模
     */
    public static boolean isOverSize(ComponentNode pre, ComponentNode post, ComponentGraph graph) {
//		if (DirSimilarity.getSimLevelOfPath(pre.getStrComponentName(), post.getStrComponentName(), pre.getNum(), post.getNum()) > 0)
//			return false;
        if (pre.getAllFiles().size() + post.getAllFiles().size() > Threshold.COMSCALE * graph.getTotalSize())
            return true;
        return false;
    }

    /**
     * 判断是否是小规模
     */
    public static boolean isMinSize(ComponentEdge ce) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        if (pre.getAllFiles().size() <= 3 || post.getAllFiles().size() <= 3)
            return true;
        return false;
    }

    /**
     * 判断是否是密集型依赖
     */
    public static boolean isIntensive(ComponentEdge ce) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        if (ce.getDependNum() / (pre.getAllFiles().size() * post.getAllFiles().size()) > Threshold.minComSim)
            return true;
        return false;
    }

    /**
     * 判断是否是独立性依赖
     */
    public static boolean isIndependent(ComponentEdge ce, ComponentGraph graph) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        if (findInfluenceSet(graph, pre, post) < Threshold.regionPreMin * 2)
            return true;
        if (findInfluenceSet(graph, pre) < Threshold.regionPreMin) {
            if (pre.getAllFiles().size() < 5 || (pre.getAllFiles().size() / post.getAllFiles().size()) <= 0.1)
                return true;
        }
        if (findInfluenceSet(graph, post) < Threshold.regionPreMin) {
            if (post.getAllFiles().size() < 5 || (post.getAllFiles().size() / pre.getAllFiles().size()) <= 0.1)
                return true;
        }
        return false;
    }

    /**
     * 计算当前组件图中，独立组件个数
     */
    public static int getExpectedNum(ComponentGraph graph) {
        int sumSeparate = 0;
        for (ComponentNode cn : graph.getAllComponents()) {
            if (graph.isSeprate(cn))
                sumSeparate++;
        }
        return sumSeparate;
    }

    public static int findInfluenceSet(ComponentGraph graph, ComponentNode pre, ComponentNode post) {
        int num = -2;// 排除本身的边
        num += graph.getPostComponents(pre).size();
        num += graph.getPostComponents(post).size();
        num += graph.getPreComponents(pre).size();
        num += graph.getPreComponents(post).size();
        return num <= 0 ? 1 : num;
    }

    public static int findInfluenceSet(ComponentGraph graph, ComponentNode pre) {
        int num = -1;// 排除本身的边
        num += graph.getPostComponents(pre).size();
        num += graph.getPreComponents(pre).size();
        return num <= 0 ? 0 : num;
    }

    /**
     * 考虑组件规模
     */
    public static double getDependDir(ComponentEdge ce, ComponentGraph graph) {
        double dependNum = ce.getDependNum();
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        double sim = DirSimilarity.getSimLevelOfNode(pre, post);
        double strength = getDependDirSize(ce, graph) / ce.getDependence() * dependNum;
        if (sim == 0)
            strength = 0;
        return strength;
    }

    /**
     * 考虑组件规模+影响边+密集性
     */
    public static double getIntense(ComponentEdge ce, ComponentGraph graph) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        double strength = ce.getDependence();//(double) ce.getDependence();
        double sim = Math.max(DirSimilarity.getSimLevelOfNode(pre, post),0.01);
        int sum = pre.getAllFiles().size()*post.getAllFiles().size();
        strength = strength / sum*sim;
        return strength;
    }

    /**
     * 考虑组件规模+影响边+密集性
     */
    public static double getIntenseMinSize(ComponentEdge ce, ComponentGraph graph) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();
        double strength = (double) ce.getDependence();
        double sim = DirSimilarity.getSimLevelOfNode(pre, post);
        strength = strength *sim;
        return strength;
    }

    public static double getDependDirSize(ComponentEdge ce, ComponentGraph graph) {
        ComponentNode pre = ce.getPreComponent();
        ComponentNode post = ce.getPostComponent();

        double multiple = 0;
        double sim = DirSimilarity.getSimLevelOfNode(pre, post);
        if (sim > 0)
            multiple = sim;
        else {
            if (pre.getAllFiles().size() < 3 || post.getAllFiles().size() < 3) {
                multiple = 0.1;
            } else {
                multiple = 0.000001;
            }
        }
        double influencePre = findInfluenceSet(graph, pre);
        double influencePost = findInfluenceSet(graph, post);
        double strength = getIntense(ce, graph) * multiple ;//* (1 / influencePost) * (1 / influencePre)
        return strength;
    }
}

